/*
 * 版权所有 (C) 2015 知启蒙(ZHIQIM) 保留所有权利。[遇见知启蒙，邂逅框架梦]
 * 
 * https://zhiqim.org/project/zhiqim_framework/zhiqim_kernel.htm
 *
 * Zhiqim Kernel is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package org.zhiqim.kernel.util;

import org.zhiqim.kernel.annotation.AnAlias;
import org.zhiqim.kernel.constants.CodeConstants;
import org.zhiqim.kernel.constants.EnumConstants;
import org.zhiqim.kernel.enumerated.LetterCase;

/**
 * 十六进制相关工具类
 * 
 * @version v1.0.0 @author zouzhigang 2014-2-27 新建与整理
 */
@AnAlias("Hexs")
public class Hexs implements CodeConstants, EnumConstants
{
    /** 得到字符串对应的16进制编码 */
    public static String toHexStringUTF8(String str)
    {
        return toHexString(str.getBytes(_UTF_8_C_));
    }
    
    /** 字节数组转16进制字符串*/
    public static String toHexString(byte[] b)
    {
        return toHexString(b, LetterCase.LOWER);
    }
    
    /** 字节数组转字符串，顺序解析 */
    public static String toHexString(byte[] b, LetterCase letterCase)
    {
        StringBuilder strb = new StringBuilder();
        for (int i=0;i<b.length;i++)
        {
            String str = Integer.toString((b[i] & 0xFF) + 0x100, 16).substring(1);
            strb.append(letterCase.toCase(str, LetterCase.LOWER));
        }
        
        return strb.toString();
    }
    
    /** 字符串转字节数组，顺序解析 */
    public static String toHexString(byte[] b, String spe)
    {
        return toHexString(b, spe, LetterCase.LOWER);
    }
    
    /** 字符串转字节数组，顺序解析，指定大小写 */
    public static String toHexString(byte[] b, String spe, LetterCase letterCase)
    {
        StringBuilder strb = new StringBuilder();
        for (int i=0;i<b.length;i++)
        {
            if (i != 0)
                strb.append(spe);
            
            String str = Integer.toString((b[i] & 0xFF) + 0x100, 16).substring(1);
            strb.append(letterCase.toCase(str, LetterCase.LOWER));
        }
        
        return strb.toString();
    }
    
    /**
     * &#x;十六进制编码
     * 
     * @param s 转化为&#x;型的十六制编码
     * @return String &#x3423;&#x3423;十六进制编码
     */
    public static String toHexStringX(String s)
    {
        return toHexString(s, "&#x", ";", null);
    }
    
    /**
     * \\u十六进制编码
     * 
     * @param   s 字符串
     * @return  String \\u3423\\u4523十六进制编码
     */
    public static String toHexStringU(String s)
    {
        return toHexString(s, "\\u", null, null);
    }
    
    /**
     * U+十六进制编码,且去重
     * 
     * @param   s 字符串
     * @return  String U+6211,U+7684十六进制编码
     */
    public static String toHexStringUPlus(String s)
    {
        String u = toHexString(s, "U+", null, ",");
        return Arrays.toFilterSameStr(u.split(","), ",");
    }
    
    /**
     * 转化为unicode十六进制编码
     * 
     * @param s         字符串
     * @param prefix    Unicode前缀，如0x,U+等
     * @param suffix    Unicode前缀，如;
     * @param separator 分隔符，如逗号和空格等
     * @return          Unicode编码如"我的"值为0x6211 0x7684或U+6211,U+7684
     */
    public static String toHexString(String s, String prefix, String suffix, String separator)
    {
        if(Validates.isEmpty(s)) 
            return _EMPTY_;
        
        StringBuilder strb = new StringBuilder();
        for (int i=0;i<s.length();i++)
        {
            char c = s.charAt(i);
            
            if (prefix != null)
                strb.append(prefix);
            
            strb.append(Integer.toHexString(c));
            
            if (suffix != null)
                strb.append(suffix);
            
            if (separator != null)
                strb.append(separator);
        }
        
        if (s.length() > 0 && separator != null)
            strb.setLength(strb.length() - separator.length());
        
        return strb.toString();
    }
    
    /*******************************************************************/
    //HEX字符串转化为byte[]
    /*******************************************************************/
    
    /** HEX 转bytes, 支持HEX中间加空格, Integer.parseInt写法*/
    public static byte[] toBytes(String hex)
    {
        return toBytes(hex, _ONE_);
    }
    
    /** HEX 转bytes, 支持HEX中间加分隔符, Integer.parseInt写法*/
    public static byte[] toBytes(String hex, String spe)
    {
        //1.对中间的分隔符进行清理
        hex = hex.replaceAll(spe, _EMPTY_);
        
        //2.把每2两位合并成一个十六进制码，如f5e9，分解成{"f5", "e9"}
        String[] hexArr = new String[hex.length() / 2];
        for (int i=0;i<hexArr.length * 2;i=i+2)
        {
            hexArr[i/2] = hex.substring(i, i+2);
        }
        
        //3.再对每个十六进制码解析成byte
        byte[] dest = new byte[hexArr.length];
        for (int i=0;i<hexArr.length;i++)
        {
            dest[i] = (byte)(Integer.parseInt(hexArr[i],16));
        }
        
        return dest;
    }
    
    /** HEX字符串的bytes 转 bytes, 支持HEX中间加空格, Integer.parseInt写法 */
    public static byte[] toBytes(byte[] hexBytes)
    {
        String hex = new String(Bytes.toCharArray(hexBytes));
        return toBytes(hex);
    }
    
    /** HEX字符串的bytes 转 bytes, 支持HEX中间加空格, Integer.parseInt写法 */
    public static byte[] toBytes(byte[] hexBytes, int off, int len)
    {
        String hex = new String(Bytes.toCharArray(hexBytes, off, len));
        return toBytes(hex);
    }
    
    /** HEX字符串的bytes 转 bytes, 支持HEX中间加分隔符, Integer.parseInt写法 */
    public static byte[] toBytes(byte[] hexBytes, String spe)
    {
        String hex = new String(Bytes.toCharArray(hexBytes));
        return toBytes(hex, spe);
    }
    
    /** HEX字符串的bytes 转 bytes, 支持HEX中间加分隔符, Integer.parseInt写法 */
    public static byte[] toBytes(byte[] hexBytes, int off, int len, String spe)
    {
        String hex = new String(Bytes.toCharArray(hexBytes, off, len));
        return toBytes(hex, spe);
    }
    
    /** 把字节转换为16进制字符 */
    public static String byteToHex(byte ib)
    {
        char[] ob = new char[2];
        ob[0] = _HEX_CHAR_[(ib >>> 4) & 0x0F];
        ob[1] = _HEX_CHAR_[ib & 0x0F];
        String s = new String(ob);
        return s;
    }
    
    /** 把字节转换为16进制字符 */
    public static String byteToHexLower(byte ib)
    {
        char[] ob = new char[2];
        ob[0] = _HEX_CHAR_LOW_[(ib >>> 4) & 0x0F];
        ob[1] = _HEX_CHAR_LOW_[ib & 0x0F];
        String s = new String(ob);
        return s;
    }
    
    /** 把16进制字符转字节 */
    public static int hexToByte(char c)
    {
        if (Character.isDigit(c))
            return c - _0_;
        else if (Character.isLowerCase(c))
            return 10 + c - _a_;
        else
            return 10 + c - _A_;
    }
    
    /** 把字节数组转换成二进制字符串 */
    public static String toBinString(byte[] b, String spe)
    {
        if (b == null || b.length == 0)
            return _EMPTY_;
        
        StringBuilder strb = new StringBuilder();
        strb.append(byteToBin(b[0]));
        for (int i=1;i<b.length;i++)
        {
            strb.append(spe).append(byteToBin(b[i]));
        }
        
        return strb.toString();
    }
    
    /** 把字节转换为二进制字符 */
    public static String byteToBin(byte ib)
    {
        char[] bin = new char[8];
        bin[0] = _BIN_CHAR_[(ib >>> 7) & 0x00000001];
        bin[1] = _BIN_CHAR_[(ib >>> 6) & 0x00000001];
        bin[2] = _BIN_CHAR_[(ib >>> 5) & 0x00000001];
        bin[3] = _BIN_CHAR_[(ib >>> 4) & 0x00000001];
        bin[4] = _BIN_CHAR_[(ib >>> 3) & 0x00000001];
        bin[5] = _BIN_CHAR_[(ib >>> 2) & 0x00000001];
        bin[6] = _BIN_CHAR_[(ib >>> 1) & 0x00000001];
        bin[7] = _BIN_CHAR_[ib         & 0x00000001];
        return new String(bin);
    }
}
